//
//  Path.m
//  ProjectL
//
//  Created by Nguyen Tan Loc on 8/16/13.
//  Copyright (c) 2013 Nguyen Tan Loc. All rights reserved.
//

#import "Path.h"
#import "MainGameScene.h"
#import "Utility.h"

@implementation Path
@synthesize _jailState = mJailState;

-(id) initWithList:(NSArray *)listNode
{
    if (self = [super init])
    {
        mListPNode = [[NSMutableArray alloc] init];
        mListPLine = [[NSMutableArray alloc] init];
        mListLight = [[NSMutableArray alloc] init];
        
        mUserBlade = [[CCBlade bladeWithMaximumPoint:40] retain];
        [mUserBlade setAutoDim:YES];
        [mUserBlade setTexture:[[CCTextureCache sharedTextureCache] addImage:@"node_tail.png"]];

        mJailState = eJS_JAIL;
        [self initObject:listNode];
    }
    
    return self;
}

-(void) initObject:(NSArray *)listNodeInfo
{
    // create node
    for (int i = 0; i < listNodeInfo.count; i++)
    {
        PNode *node = [listNodeInfo objectAtIndex:i];
        [mListPNode addObject:node];
    }
    
    for (int i = 0; i < mListPNode.count - 1; i++)
    {
        PNode *node = [mListPNode objectAtIndex:i];
        PNode *nextNode = [mListPNode objectAtIndex:(i + 1)];
        node._nextNode = nextNode;
        
        PLine *line = [[PLine alloc] initWithNode:node];
        node._line = line;
        
        PSmallLight *smallLight = [[PSmallLight alloc] initWithLine:line];
        
        [mListPLine addObject:line];
        [line release];
        
        [mListLight addObject:smallLight];
        [smallLight release];
    }
    
    mUserNode = [[PNode alloc] initWithType:eNT_USER_NODE];
    [mUserNode setColor:[[LevelManager getInstance] getWorldColor]];
    mUserNode._nextNode = [self getFirstNode];
    [mUserNode setPosition:ccp(-100, -100)];
    mUserBlade.color = ccc4f(mUserNode.color.r * 0.5 / 255.0f, mUserNode.color.g * 0.5 / 255.0f, mUserNode.color.b * 0.5 / 255.0f, 0.5);
//    mUserNode.visible = NO;
    
    mNodeIndicator = [[PNodeIndicator alloc] initWithNode:[self getFirstNode]];
    [mNodeIndicator setPosition:[self getFirstNode].position];
    
    mUserLine = [[PLine alloc] initWithNode:mUserNode];
    mUserLine.visible = NO;
    mUserLine._inverse = YES;
    [mUserLine setLineState:eLS_CONTECTED];
    
}

-(void) addToBatch:(CCSpriteBatchNode *)batch
{
    [self addChild:mUserBlade];
    [mUserBlade release];
    
    for (int i = 0; i < mListPLine.count; i++)
    {
        PLine *line = [mListPLine objectAtIndex:i];
        [self addChild:line];
    }
    
    [self addChild:mUserLine z:0];
    [mUserLine release];
    
    for (int i = 0; i < mListPNode.count; i++)
    {
        PNode *node = [mListPNode objectAtIndex:i];
        [batch addChild:node z:Z_ORDER_PATH_NODE];
    }
    
    [batch addChild:mNodeIndicator];
    [mNodeIndicator release];
    
    [batch addChild:mUserNode z:Z_ORDER_USER_NODE];
    [mUserNode release];
    
    for (int i = 0; i < mListLight.count; i++)
    {
        PSmallLight *light = [mListLight objectAtIndex:i];
        [batch addChild:light z:Z_ORDER_SMALL_LIGHT];
    }
    
    
    // add virus
    if (mSpreadTime > 0)
    {
        mVirus = [CCSprite spriteWithSpriteFrameName:SFN_VIRUS];
        [mVirus setPosition:mVirusPos];
        [batch addChild:mVirus z:Z_ORDER_VIRUS];
    }
    
    // add dot circle and hint
    mDotCircle = [CCSprite spriteWithSpriteFrameName:SFN_CIRCLE_100];
    [mDotCircle setPosition:mUserNode.position];
    [batch addChild:mDotCircle z:Z_ORDER_MAGNET_ZONE];
    
//    mHint = [[CCLabelBMFont alloc] initWithString:@"Tap circle to start" fntFile:FONT_DEFAULT];
    mHint = [[CCLabelBMFont alloc] initWithString:@"" fntFile:FONT_DEFAULT];
    [mHint setWidth:uniPos(80, 160)];
    [mHint setAnchorPoint:ccp(0.5, 0)];
    [mHint setPosition:ccpAdd(mDotCircle.position, uniPos(ccp(0, 30), ccp(0, 60)))];
//    [mHint setScale:0];
    [self addChild:mHint z:100];
    [mHint release];
}

-(void) connectWithNode:(PNode *)node
{
    if (node._state == eNS_CONTECTED)
        return;
    
    [node setColor:[[LevelManager getInstance] getWorldColor]];
    node._state = eNS_CONTECTED;
    mUserNode._nextNode = node;
    [mUserLine reset];
    
    if (node._nextNode != nil)
    {
        node._nextNode._state = eNS_CONNECTING;
        mNodeIndicator._node = node._nextNode;
        [mNodeIndicator setPosition:[node._nextNode getRealPosition]];
    }
    else
    {
        [mNodeIndicator setVisible:NO];
    }
    
    int index = (int)node.tag - 1;
    if (index < 0)
    {
        [mUserLine setVisible:YES];
        
        // set visible fail to sleeping virus
        if (mVirusSleeping != nil)
        {
            [mVirusSleeping stopAllActions];
            CCFadeTo *fadeTo = [CCFadeTo actionWithDuration:0.2 opacity:0];
            [mVirusSleeping runAction:fadeTo];
        }
        
//        [mUserNode setVisible:YES];
        return;
    }
    
    PLine *line = [mListPLine objectAtIndex:index];
    PSmallLight *light = [mListLight objectAtIndex:index];
    
    [line setLineState:eLS_CONTECTED];
    [light setVisible:NO]; 
}

-(void) processTouch:(UITouchPhase)touchPhase position:(CGPoint)position
{
    if (touchPhase == UITouchPhaseBegan)
    {
        [mUserNode setPosition:position];
    }
    else if (touchPhase == UITouchPhaseMoved)
    {
        [mUserNode setPosition:position];
    }
    else if (touchPhase == UITouchPhaseEnded)
    {
        
    }
}

-(void) setSpreadTime:(float)spreadTime
{
    mSpreadTime = spreadTime;
}

-(void) addActions:(NSArray *)actions
{
    
}

-(void) setVirusPos:(CGPoint)pos
{
    mVirusPos = pos;
    
    // add z..z..z here
//    for (int i = 0; i < 3; i++)
    {
        mVirusSleeping = [CCLabelBMFont labelWithString:@"z" fntFile:FONT_DEFAULT];
        [mVirusSleeping setPosition:ccp(mVirusPos.x, mVirusPos.y + uniPos(10, 20))];
        [self addChild:mVirusSleeping z:0 tag:(166 + 0)];
        
        
        CCCallBlock *callBlock = [CCCallBlock actionWithBlock:^{
            [mVirusSleeping setScale:0];
            [mVirusSleeping setOpacity:255];
            [mVirusSleeping setPosition:ccp(mVirusPos.x, mVirusPos.y + uniPos(20, 40))];
        }];

        CCMoveTo *moveTo = [CCMoveTo actionWithDuration:1.5 position:ccp(mVirusPos.x + uniPos(20, 40), mVirusPos.y + uniPos(40, 80))];
        CCScaleTo *scaleTo = [CCScaleTo actionWithDuration:1 scale:1];
        CCSpawn *spawn = [CCSpawn actions:moveTo, scaleTo, nil];
        CCFadeTo *fadeTo = [CCFadeTo actionWithDuration:0.2 opacity:0];
        CCSequence *sequence = [CCSequence actions:callBlock, spawn, fadeTo, nil];
        CCRepeatForever *repeat = [CCRepeatForever actionWithAction:sequence];
        
        
        [mVirusSleeping runAction:repeat];
    }
}

-(void) startSpread
{
    if (mSpreadTime > 0)
    {
        CCMoveTo *moveTo = [CCMoveTo actionWithDuration:mSpreadTime position:[[self getFirstNode] getRealPosition]];
        CCRotateBy *rotateBy = [CCRotateBy actionWithDuration:mSpreadTime angle:mSpreadTime * 360];
        CCSpawn *spawn = [CCSpawn actions:moveTo, rotateBy, nil];
        CCScaleTo *scaleTo = [CCScaleTo actionWithDuration:0.3 scale:0];
        CCCallBlock *callBlock =[CCCallBlock actionWithBlock:^{
            [[self getFirstNode] spread];
        }];
        CCSequence *sequence = [CCSequence actions:spawn, scaleTo, callBlock, nil];
        [mVirus runAction:sequence];
        
//        CCDelayTime *delay = [CCDelayTime actionWithDuration:mSpreadTime];
//        CCCallFunc *callFunc = [CCCallFunc actionWithTarget:self selector:@selector(spread)];
//        CCSequence *sequence = [CCSequence actionOne:delay two:callFunc];
//        
//        [self runAction:sequence];
    }
}

-(void) startAction
{
    for (int i = 0; i < mListLight.count; i++)
    {
        PSmallLight *light = [mListLight objectAtIndex:i];
        [light startAction];
    }
    
    for (int i = 0; i < mListPNode.count; i++)
    {
        PNode *node = [mListPNode objectAtIndex:i];
        [node startAction];
    }
    
//    [self scheduleUpdate];
}

-(void) stopAction
{
    [self stopAllActions];
    
    for (int i = 0; i < mListLight.count; i++)
    {
        PSmallLight *light = [mListLight objectAtIndex:i];
        [light stopAction];
    }
    
    for (int i = 0; i < mListPNode.count; i++)
    {
        PNode *node = [mListPNode objectAtIndex:i];
        [node stopAction];
    }
}

-(void) jailBreak
{
    if (mJailState != eJS_JAIL)
        return;
    
    mJailState = eJS_JAIL_BREAKING;
    [self showHintCount];
}

-(void) showCountOnUserNode
{
    [mHint setPosition:ccpAdd([mUserNode getRealPosition], uniPos(ccp(0, 20), ccp(0, 40)))];
    [mHint setColor:ccc3(255, 255, 255)];
    [mHint resumeSchedulerAndActions];
    [self showHintCount];
}

-(void) showHintCount
{
    [mHint stopAllActions];
//    CCLOG(@"show hint count");
//    [mHint setString:@"3"];
//    [mHint setScale:0];
    
//    CCDelayTime *d = [CCDelayTime actionWithDuration:0.5];
//    
//    CCScaleTo *s1 = [CCScaleTo actionWithDuration:0.2 scale:1];
//    CCCallBlock *sound1 = [CCCallBlock actionWithBlock:^{
//        [[Utility getInstance] playEffect:SOUND_TICK];
//    }];
//    CCEaseBackOut *e1 = [CCEaseBackOut actionWithAction:s1];
//    CCDelayTime *d1 = [CCDelayTime actionWithDuration:0.8];
//    CCCallBlock *c1 = [CCCallBlock actionWithBlock:^{
//        [mHint setString:@"2"];
//        [mHint setScale:0];
//    }];
    
    // reduce time
    [mHint setString:@"2"];
    [mHint setScale:0];
    
    CCScaleTo *s2 = [CCScaleTo actionWithDuration:0.2 scale:1];
    CCCallBlock *sound2 = [CCCallBlock actionWithBlock:^{
        [[Utility getInstance] playEffect:SOUND_TICK];
    }];
    CCEaseBackOut *e2 = [CCEaseBackOut actionWithAction:s2];
    CCDelayTime *d2 = [CCDelayTime actionWithDuration:0.4];
    CCCallBlock *c2 = [CCCallBlock actionWithBlock:^{
        [mHint setString:@"1"];
        [mHint setScale:0];
    }];
    
    CCScaleTo *s3 = [CCScaleTo actionWithDuration:0.2 scale:1];
    CCCallBlock *sound3 = [CCCallBlock actionWithBlock:^{
        [[Utility getInstance] playEffect:SOUND_TICK];
    }];
    CCEaseBackOut *e3 = [CCEaseBackOut actionWithAction:s3];
    CCDelayTime *d3 = [CCDelayTime actionWithDuration:0.4];
    CCCallBlock *c3 = [CCCallBlock actionWithBlock:^{
        [mHint setString:@"Go!"];
        [mHint setScale:0];
        [mHint setColor:CL_PANEL_BTN];
        
    }];
    
    CCScaleTo *s4 = [CCScaleTo actionWithDuration:0.2 scale:1];
    CCCallBlock *sound4 = [CCCallBlock actionWithBlock:^{
        [[Utility getInstance] playEffect:SOUND_GO];
    }];
    CCEaseBackOut *e4 = [CCEaseBackOut actionWithAction:s3];
    CCCallBlock *c4 = [CCCallBlock actionWithBlock:^{
        CCFadeTo *fadeTo = [CCFadeTo actionWithDuration:0.2 opacity:0];
        [mDotCircle runAction:fadeTo];
        mJailState = eJS_JAIL_BREAKED;
        [[NSNotificationCenter defaultCenter] postNotificationName:EVENT_ON_COUNT_DONE object:nil];
    }];
    CCDelayTime *d4 = [CCDelayTime actionWithDuration:0.4];
    CCScaleTo *s5 = [CCScaleTo actionWithDuration:0.2 scale:0];
    
//    CCSequence *seq = [CCSequence actions:d, s1, sound1, e1, d1, c1, s2, sound2, e2, d2, c2, s3, sound3, e3, d3, c3, s4, sound4, e4, c4, d4, s5, nil];
    CCSequence *seq = [CCSequence actions:s2, sound2, e2, d2, c2, s3, sound3, e3, d3, c3, s4, sound4, e4, c4, d4, s5, nil];
    [mHint runAction:seq];
}

-(void) updateUserNode:(ccTime)delta
{
    
    float newX = [mUserNode getRealPosition].x + mGravity.x * delta;
    float newY = [mUserNode getRealPosition].y + mGravity.y * delta;
    
    if (mJailState != eJS_JAIL_BREAKED)
    {
        CGPoint sub = ccpSub(ccp(newX, newY), mDotCircle.position);
        float distance = ccpLength(sub);
        float radius = mDotCircle.contentSize.width / 2 - mUserNode.contentSize.width / 2;
        if (distance > radius)
        {
            float angle = atan2f(sub.y, sub.x);

//            CCLOG(@"angle = %f", CC_RADIANS_TO_DEGREES(angle));
            newX = [mDotCircle position].x + cosf((angle)) * radius;
            newY = [mDotCircle position].y + sinf((angle)) * radius;
        }
    }
    else
    {
        newX = max(newX, mUserNode.contentSize.width / 2);
        newX = min(newX, [CCDirector sharedDirector].winSize.width - mUserNode.contentSize.width / 2);
        
        newY = max(newY, uniPos(40, 80) + mUserNode.contentSize.height / 2);
        newY = min(newY, [CCDirector sharedDirector].winSize.height - mUserNode.contentSize.height / 2 - uniPos(40, 80));
    }
    
    [mUserNode setPosition:ccp(newX, newY)];
    [mUserBlade push:ccp(newX, newY)];
    
    if ([MainGameScene getInstance]._darkFog != nil)
    {
        [[MainGameScene getInstance]._darkFog setSpotLightPosition:[mUserNode getRealPosition]];
    }
    
    
    // check if next node is out of screen
    if (mUserNode._nextNode._nextNode != nil && [MainGameScene getInstance]._mainGameState == sMG_STARTING)
    {
        if ([mUserNode._nextNode._nextNode getRealPosition].y < uniPos(-30, -60))
        {
            [[MainGameScene getInstance] endGame:eGT_NODE_OUT_OF_SCREEN];
        }
    }
}

-(CGRect) getDotCirleRect
{
//    float radius = mDotCircle.contentSize.width / 2;
//    return CGRectMake(mDotCircle.position.x - radius,
//                      mDotCircle.position.y - radius,
//                      radius * 2,
//                      radius * 2);
    
    CGSize winSize = [[CCDirector sharedDirector] winSize];
    float size = uniPos(50, 100);
    return CGRectMake(0,
                      size,
                      winSize.width,
                      winSize.height - size);
}

-(void) setGravity:(CGPoint)pt
{
    mGravity = pt;
}

-(PNode *) getFirstNode
{
    return [mListPNode objectAtIndex:0];
}

-(PNode *) getUserNode
{
    return mUserNode;
}

-(CCBlade *) getUserBlade
{
    return mUserBlade;
}
-(PLine *) getUserLine
{
    return mUserLine;
}

-(void) hideUserStuff
{
    [mUserLine setVisible:NO];
    [mUserNode setVisible:NO];
}

-(void) pauseSchedulerAndActions
{
    [super pauseSchedulerAndActions];
    [mHint pauseSchedulerAndActions];
}

-(void) resumeSchedulerAndActions
{
    [super resumeSchedulerAndActions];
    [mHint resumeSchedulerAndActions];
}

-(void) dealloc
{
    [mListPNode removeAllObjects];
    [mListPNode release];
    mListPNode = nil;
    
    [mListPLine removeAllObjects];
    [mListPLine release];
    mListPLine = nil;
    
    [mListLight removeAllObjects];
    [mListLight release];
    mListLight = nil;
    
    [super dealloc];
    
    CCLOG(@"Path dealloc!");
}

@end
